import React, { Component } from 'react'
import { Button, Modal, Input, Form, message, Select, Table } from 'antd'
import cloneDeep from 'lodash/cloneDeep'

import { list2Tree, treeFind } from '../utils/treeUtils'
import request from '@/Utils/fecth'
import { address } from '@/Utils/apiConfig'
import routerList from '@/Utils/router.config'

import './index.less'

const { resource } = address

export default class Permissions extends Component {
  constructor(props) {
    super(props)
    this.state = {
      treeData: [],
      visible: false,
      value: '',
    }
    this.currentNode = {} // 当前节点
    this.parentNode = {} // 父节点
    this.flag = 'add'
  }

  componentDidMount() {
    this.getList()
  }

  autoGenerateTree = () => {
    Modal.confirm({
      title: '确定自动生成菜单吗?',
      onOk: async() => {
        await generateTree(routerList)
        message.success('菜单生成成功')
        this.getList()
      },
    })
  }

  getList = async() => {
    const { status, data = {}} = await request().get(resource.getList)
    if (status === 200) {
      const list = (data.data || []).map(v => {
        return {
          ...v,
          id: v.id,
          name: v.name,
          parentId: v.parent_id,
        }
      })
      const treeData = list2Tree(cloneDeep(list))
      this.setState({
        treeData,
      })
    }
  }

  // 删除文件操作
  deleteTreeNode = async(treeNode) => {
    Modal.confirm({
      title: `确定删除${treeNode.name}菜单吗？`,
      onOk: async() => {
        const { status } = await request().delete(resource.getDetail.format({ id: treeNode.id }))
        if (status === 200) {
          message.success('删除成功')
          this.getList()
        }
      },
    })
  }

  updateTreeNode = async(values) => {
    const { status } = await request().put(resource.getDetail.format({ id: this.currentNode.id }), {
      ...values,
      parentId: this.currentNode.parentId || '',
    })
    if (status === 200) {
      message.success('修改成功')
      this.setState({
        visible: false,
      })
      this.getList()
    }
  }

  /**
   *
   * @param {添加节点} values
   */
  addTreeNode = async(values) => {
    const { name, resourceUrl, type, method = '' } = values || {}
    const { status, data } = await request().post(resource.getList, {
      name,
      type,
      resourceUrl,
      parentId: this.parentNode.id || '',
      method,
    })
    if (status >= 200 && status < 400) {
      message.success('添加成功')
      this.getList()
      this.setState({
        visible: false,
      })
    }
  }

  columns = [
    {
      dataIndex: 'name',
      title: '菜单名称',
    },
    {
      dataIndex: 'resource_url',
      title: 'resourceUrl',
    },
    {
      dataIndex: 'type',
      title: '权限级别',
    },
    {
      dataIndex: 'method',
      title: '接口请求方法',
      render: v => v || '--',
    },
    {
      dataIndex: 'handle',
      title: '操作',
      render: (v, record, ...args) => {
        return <div>
          <span className={`common-operation`} onClick={() => this.onOpenModal(record, 'check')}>查看</span>
          <span className={`common-operation`} onClick={() => this.onOpenModal(record, 'update')}>修改</span>
          <span className={`common-operation`} onClick={() => this.deleteTreeNode(record)}>删除</span>
          <span className={`common-operation`} onClick={() => this.addNode(record, 'add')}>添加子菜单</span>
        </div>
      },
    },
  ]

  onFinish = (values) => {
    this.flag === 'add' && this.addTreeNode(values)
    this.flag === 'update' && this.updateTreeNode(values)
    this.flag === 'check' && this.setState({
      visible: false,
    })
  }

  onOpenModal = (currentNode, flag) => {
    if (currentNode.parentId) {
      const { treeData } = this.state
      const parentNode = treeFind(treeData, (v) => v.id === currentNode.parentId) || {}
      this.parentNode = {
        ...parentNode,
        resourceUrl: parentNode.resource_url,
      }
    } else {
      this.parentNode = {}
    }
    // 查看
    this.currentNode = {
      ...currentNode,
      resourceUrl: currentNode.resource_url,
    }
    this.flag = flag
    this.setState({
      visible: true,
    })
  }

  /**
   * 添加子菜单
   * @param {} parentNode
   * @param {*} flag
   */
  addNode = (parentNode = {}, flag) => {
    this.flag = flag
    this.currentNode = {}
    this.parentNode = {
      ...parentNode,
      resourceUrl: parentNode.resource_url,
    }
    this.setState({
      visible: true,
    })
  }

  render() {
    const {
      treeData,
      visible,
    } = this.state
    return (
      <div className="admin">
        <Table
          rowKey={'id'}
          dataSource={treeData}
          pagination={false}
          columns={this.columns}
        />
        <Button className="mt24" type="dashed" onClick={() => this.addNode({}, 'add')} block>添加子菜单</Button>
        {
          !treeData.length &&
        <Button className="mt24" type="primary" danger onClick={this.autoGenerateTree} block>自动生成菜单</Button>
        }
        <Modal
          centered
          destroyOnClose
          name={`添加菜单`}
          onCancel={() => this.setState({ visible: false })}
          visible={visible}
          onOk={() => this.form && this.form.submit()}
          width={650}
          maskClosable={false}>
          <Form
            className="mt24"
            autoComplete="false"
            {...{
              labelCol: { span: 6 },
              wrapperCol: { span: 16 },
            }}
            onFinish={this.onFinish}
            ref={c => this.form = c}
          >
            {
              this.parentNode.name &&
              <Form.Item
                label="父菜单名称:"
                name="pName"
                initialValue={this.parentNode.name}
              >
                <Input disabled maxLength={30} />
              </Form.Item>
            }
            {
              this.parentNode.id &&
              <Form.Item
                label="父菜单resourceUrl:"
                name="parent_resourceUrl"
                initialValue={this.parentNode.resourceUrl}
              >
                <Input disabled maxLength={30} />
              </Form.Item>
            }
            <Form.Item
              label="菜单名称:"
              name="name"
              initialValue={this.currentNode.name}
              rules={[
                { required: true, message: '请输入菜单名称' },
              ]}
            >
              <Input maxLength={30} placeholder="请输入菜单名称" />
            </Form.Item>
            <Form.Item
              label="resourceUrl:"
              name="resourceUrl"
              initialValue={this.currentNode.resourceUrl}
              rules={[
                { required: true, message: '请输入页面链接或接口名称' },
              ]}
            >
              <Input placeholder="请输入页面链接或接口名称" />
            </Form.Item>
            <Form.Item
              label="权限级别:"
              name="type"
              initialValue={this.currentNode.type}
              rules={[
                { required: true, message: '请选择权限级别' },
              ]}
            >
              <Select placeholder="请选择权限级别">
                {
                  Types.map(v => {
                    return <Select.Option key={v.id} value={v.id}>{v.label}</Select.Option>
                  })
                }
              </Select>
            </Form.Item>
            <Form.Item
              label="接口请求方法:"
              name="method"
              initialValue={this.currentNode.method}
            >
              <Select placeholder="请选择权限级别">
                {
                  methodList.map(v => {
                    return <Select.Option key={v.id} value={v.id}>{v.label}</Select.Option>
                  })
                }
              </Select>
            </Form.Item>
          </Form>
        </Modal>
      </div>
    )
  }
}

const Types = [
  {
    label: 'Menu级别',
    id: 'menu',
  },
  {
    label: 'Page级别',
    id: 'page',
  },
  {
    label: 'Button级别',
    id: 'button',
  },
]
const methodList = [
  {
    label: 'GET',
    id: 'GET',
  },
  {
    label: 'POST',
    id: 'POST',
  },
  {
    label: 'DELETE',
    id: 'DELETE',
  },
  {
    label: 'PUT',
    id: 'PUT',
  },
]

async function generateTree(arr, parentId = '') {
  for (let i = 0; i < arr.length; i++) {
    const { name, resourceUrl, type, method, children = [] } = arr[i] || {}
    const { status, data = {}} = await request().post(resource.getList, {
      name,
      type,
      resourceUrl,
      parentId,
      method,
    })
    await wait(500)
    if (status >= 200 && status < 400 && children.length && data.id) {
      await generateTree(children, data.id)
    }
  }
}

const wait = (timeout) => new Promise(resolve => setTimeout(resolve, timeout))
